package com.province.platform.core.utils;

import com.province.platform.common.enums.CommonErrorCode;
import com.province.platform.common.exception.PlatformException;
import com.province.platform.common.utils.Configuration;
import com.province.platform.core.constants.CoreConstants;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Objects;
import java.util.Properties;

public class SecretUtils {
    private static final String ENCODING = "utf-8";
    private static final String AES_KEY = "OTtrIEiBD9HohCP0";
    public static final String KEY_ALGORITHM_AES = "AES";
    private static final String CIPHER_ALGORITHM_AES = "AES/ECB/PKCS5Padding";
    public static final String KEY_ALGORITHM_RSA = "RSA";
    public static final String KEY_ALGORITHM_3DES = "DESede";
    private static final String CIPHER_ALGORITHM_3DES = "DESede/ECB/PKCS5Padding";

    public static Configuration decryptSecretKey(Configuration config) {
        String keyType = config.getString(CoreConstants.JOB_SETTING_KEY_TYPE);
        if (StringUtils.isBlank(keyType)) {
            return config;
        }
        String privateKey = config.getString(CoreConstants.JOB_SETTING_PRIVATE_KEY);
        if (StringUtils.isBlank(privateKey)) {
            throw PlatformException.asPlatformException(CommonErrorCode.CONFIG_ERROR,
                    String.format("配置的密钥类型为[%s]，但没有配置私钥", keyType));
        }

        for (String key: config.getKeys()) {
            int lastKeyIndex = key.lastIndexOf(".") + 1;
            String lastKey = key.substring(lastKeyIndex);
            if (lastKey.length() > 1 && lastKey.charAt(0) == '*' && lastKey.charAt(1) != '*') {
                Object value = config.get(key);
                if (value instanceof String) {
                    String newKey = key.substring(0, lastKeyIndex) + lastKey.substring(1);
                    config.set(newKey, SecretUtils.decrypt(keyType, privateKey, (String) value));
                    config.remove(key);
                }
            }
        }

        return config;
    }

    public static byte[] decryptBASE64(String data) {
        return Base64.getDecoder().decode(data);
    }

    public static byte[] encryptBASE64(byte[] data) {
        return Base64.getEncoder().encode(data);
    }

    public static String decryptAES(String data) {
        try {
            // 获取密钥
            SecretKeySpec secretKeySpec = new SecretKeySpec(AES_KEY.getBytes(ENCODING), KEY_ALGORITHM_AES);

            // 解密数据
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_AES);
            cipher.init(Cipher.DECRYPT_MODE,  secretKeySpec);
            return new String(cipher.doFinal(decryptBASE64(data)), ENCODING);
        } catch (Exception e) {
            throw PlatformException.asPlatformException(CommonErrorCode.SECRET_ERROR, KEY_ALGORITHM_AES + "解密异常", e);
        }
    }

    public static String encryptAES(String data) {
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(AES_KEY.getBytes(ENCODING), KEY_ALGORITHM_AES);

            // 加密数据
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_AES);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            return new String(encryptBASE64(cipher.doFinal(data.getBytes(ENCODING))));
        } catch (Exception e) {
            throw PlatformException.asPlatformException(CommonErrorCode.SECRET_ERROR, KEY_ALGORITHM_AES + "加密异常", e);
        }
    }

    public static String decrypt(String keyType, String privateKey, String data) {
        if (SecretUtils.KEY_ALGORITHM_3DES.equals(keyType)) {
            return SecretUtils.decrypt3DES(data, privateKey);
        } else if (SecretUtils.KEY_ALGORITHM_RSA.equals(keyType)) {
            return SecretUtils.decryptRSA(data, privateKey);
        }
        throw PlatformException.asPlatformException(CommonErrorCode.SECRET_ERROR, String.format("不支持的加密类型[%s]", keyType));
    }

    public static String decryptRSA(String data, String key) {
        try {
            // 解密密钥
            byte[] keyBytes = decryptBASE64(key);

            // 取得密钥
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_RSA);
            Key privateKey = keyFactory.generatePrivate(keySpec);

            // 解密数据
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE,  privateKey);
            return new String(cipher.doFinal(decryptBASE64(data)), ENCODING);
        } catch (Exception e) {
            throw PlatformException.asPlatformException(CommonErrorCode.SECRET_ERROR, KEY_ALGORITHM_AES + "解密异常", e);
        }
    }

    public static String decrypt3DES(String data, String key) {
        try {
            // 解密密钥
            byte[] keyBytes = decryptBASE64(key);

            // 取得密钥
            SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, KEY_ALGORITHM_3DES);

            // 解密数据
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_3DES);
            cipher.init(Cipher.DECRYPT_MODE,  secretKeySpec);
            return new String(cipher.doFinal(decryptBASE64(data)), ENCODING);
        } catch (Exception e) {
            throw PlatformException.asPlatformException(CommonErrorCode.SECRET_ERROR, KEY_ALGORITHM_3DES + "解密异常", e);
        }
    }
}
